package org.dht.com.tra.nw;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

import org.apache.log4j.Logger;
import org.dht.com.msg.MalformedMessageException;
import org.dht.com.msg.Message;
import org.dht.com.msg.MessageXML;
import org.dht.com.tra.Communicator;

/**
 * The <code>MulticastManagerNetworkLAN</code> class implemented the transfer
 * messages on multicast UDP
 * 
 */
public class MulticastManagerNetworkLAN implements Communicator {

	/**
	 * Logger
	 */
	private static final Logger logger = Logger
			.getLogger(MulticastManagerNetworkLAN.class);

	/**
	 * Is the size of the buffer used for receiving messages.
	 */
	private long bufferSize = 1024;

	/**
	 * Is the {@code MulticastSocket} used for sending and receiving messages.
	 */
	private MulticastSocket multicastSocket;

	/**
	 * Is the group that will be communicating by multicast.
	 */
	private InetAddress group;

	/**
	 * Is the buffer used for a DatagramPacket when reading a message.
	 */
	private byte[] buffer;

	/**
	 * Stores the value of the port used for the UDP Multicast communication.
	 */
	private int portMulticast;

	/**
	 * Builds a MulticastManagerNetworkLAN and started multicast socket
	 * 
	 * @param portMulticast
	 *            Port multicast
	 * @param group
	 *            Internet address multicast
	 * @param bufferSize
	 *            Buffer size for to reader
	 */
	public MulticastManagerNetworkLAN(int portMulticast, InetAddress group,
			long bufferSize) {
		try {
			this.portMulticast = portMulticast;

			this.multicastSocket = new MulticastSocket(portMulticast);

			this.group = group;

			this.multicastSocket.joinGroup(group);

			this.buffer = new byte[(int) bufferSize];
		} catch (IOException e) {
			logger.error("Error creating multicast socket", e);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * co.edu.uniquindio.utils.communication.transfer.Communicator#reciever()
	 */
	public Message reciever() {
		DatagramPacket datagramPacket;
		String string;
		Message message;

		datagramPacket = new DatagramPacket(buffer, buffer.length);

		try {
			multicastSocket.receive(datagramPacket);

			string = new String(datagramPacket.getData(), 0,
					datagramPacket.getLength());

			message = MessageXML.valueOf(string);

			return message;
		} catch (IOException e) {
			logger.error("Error reading multicast socket", e);
		} catch (MalformedMessageException e) {
			logger.error("Error reading messages", e);
		}

		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * co.edu.uniquindio.utils.communication.transfer.Communicator#send(co.edu
	 * .uniquindio.utils.communication.message.Message)
	 */
	public void send(Message message) {
		DatagramPacket datagramPacket;
		String string = message.toString();

		datagramPacket = new DatagramPacket(string.getBytes(), string.length(),
				group, portMulticast);

		try {
			multicastSocket.send(datagramPacket);
		} catch (IOException e) {
			logger.error("Error writting multicast socket", e);
		}
	}

	/**
	 * Gets buffer size to reader
	 * 
	 * @return Buffer size
	 */
	public long getBufferSize() {
		return bufferSize;
	}

	/**
	 * Sets buffer size to reader
	 * 
	 * @param bufferSize
	 *            Buffer size
	 */
	public void setBufferSize(long bufferSize) {
		this.bufferSize = bufferSize;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see co.edu.uniquindio.utils.communication.transfer.Stoppable#stop()
	 */
	public void stop() {
		multicastSocket.close();
	}

}
